package com.freight.user.serviceimpl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.freight.core.common.constant.CommonConstant;
import com.freight.core.common.exception.FreightException;
import com.freight.core.common.redis.RedisTemplateHelper;
import com.freight.core.common.utils.ObjectUtil;
import com.freight.core.common.utils.SecurityUtil;
import com.freight.core.common.vo.SearchVo;
import com.freight.core.entity.User;
import com.freight.core.service.OperationLogService;
import com.freight.core.service.UserService;
import com.freight.msg.entity.Message;
import com.freight.msg.entity.MessageSend;
import com.freight.msg.service.MessageSendService;
import com.freight.msg.service.MessageService;
import com.freight.msg.utils.MyJPushClient;

import com.freight.user.dao.*;
import com.freight.user.dto.UserLoginDto;
import com.freight.user.entity.*;
import com.freight.user.mapper.*;
import com.freight.user.service.*;
import com.freight.user.util.UserDtoUtils;
import com.freight.user.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.util.*;


@Slf4j
@Service
@Transactional
public class UserLoginServiceImpl implements UserLoginService {

    @Autowired
    private UserLoginDao userLoginDao;

    @Autowired
    private DriverVoMapper driverVoMapper;

    @Autowired
    SecurityUtil securityUtil;

    @Autowired
    ICompanyVoService iCompanyVoService;

    @Autowired
    IDriverVoService iDriverVoService;

    @Autowired
    UserService userService;

    @Autowired
    private IdCardDao idCardDao;

    @Autowired
    private RedisTemplateHelper redisTemplate;

    @Autowired
    private CompanyUserService companyUserService;

    @Autowired
    private DriverUserService driverUserService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private MessageSendService messageSendService;

    @Autowired
    private OperationLogService operationLogService;

    @Override
    public UserLoginDao getRepository() {
        return userLoginDao;
    }

    @Override
    public Page<UserLogin> findByCondition(UserLogin userLogin, SearchVo searchVo, Pageable pageable) {

        return userLoginDao.findAll(new Specification<UserLogin>() {
            @Nullable
            @Override
            public Predicate toPredicate(Root<UserLogin> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {

                // TODO 可添加你的其他搜索过滤条件 默认已有创建时间过滤
                Path<Date> createTimeField = root.get("createTime");

                List<Predicate> list = new ArrayList<>();

                // 创建时间
                if (StrUtil.isNotBlank(searchVo.getStartDate()) && StrUtil.isNotBlank(searchVo.getEndDate())) {
                    Date start = DateUtil.parse(searchVo.getStartDate());
                    Date end = DateUtil.parse(searchVo.getEndDate());
                    list.add(cb.between(createTimeField, start, DateUtil.endOfDay(end)));
                }

                Predicate[] arr = new Predicate[list.size()];
                cq.where(list.toArray(arr));
                return null;
            }
        }, pageable);
    }

    @Override
    public List<UserLogin> findByUserIds(List<Long> userIds) {
        return userLoginDao.findAllByUserIdIn(userIds);
    }

    @Override
    public HashMap<Long, UserLogin> findMapByUserIds(List<Long> userIds) {
        List<UserLogin> res = userLoginDao.findAllByUserIdIn(userIds);
        HashMap<Long, UserLogin> result = new HashMap<>();
        for (UserLogin re : res) {
            result.put(re.getUserId(), re);
        }
        return result;
    }

    @Override
    public void updateUserLogin(UserLoginDto userLoginDto) {
        User u = securityUtil.getCurrUser();
        if (u == null) {
            throw new FreightException("登入失效或尚未登入，请先登入");
        }
        UserLogin userLogin = userLoginDao.findByUserId(u.getId());
        if (userLogin == null) {
            userLogin = new UserLogin();
            userLogin.setUserId(u.getId());
        }
        ObjectUtil.copyPropertiesIgnoreNull(userLoginDto, userLogin);
        userLoginDao.save(userLogin);
    }

    @Override
    public UserInfoVo getUserInfoVo() {
        User u = securityUtil.getCurrUser();
        if (u == null) {
            throw new FreightException("登入失效或尚未登入，请先登入");
        }
        User uu = userService.get(u.getId());
        UserInfoVo userInfoVo = new UserInfoVo();
        ObjectUtil.copyPropertiesIgnoreNull(uu, userInfoVo);

        if (uu.getUserType() == CommonConstant.USER_TYPE_COMPANY) {
            CompanyInfoVo company = iCompanyVoService.getCompanyInfoVoByUserId(uu.getId());
            userInfoVo.setCompanyInfoVo(company);
        }
        if (uu.getUserType() == 1) {
            DriverInfoVo driver = iDriverVoService.getDriverInfoByUserId(uu.getId());
            userInfoVo.setDriverInfoVo(driver);
        }

        return userInfoVo;
    }

    @Override
    public String updateRegistStatus(Long userId, Integer registState,String reason) {
        User userAdmin = securityUtil.getCurrUser();

        User u = userService.get(userId);
        String logContent = "";

        if (u.getUserType() == CommonConstant.USER_TYPE_DRIVER){

            //司机
            DriverUser driverUser=driverUserService.findByUserId(userId);
            driverUser.setDriverUserStatus(registState);

            String notificationTitle = "实名认证";
            String msgTitle = "实名认证";
            String msgContent = "";
            if(registState == 0){
                //审核未通过，发送消息通知原因
                Message message = new Message();
                message.setTitle("实名认证");
                String content="您的提交的“实名认证”审核未通过，原因："+reason+"。";
                logContent="实名认证信息审核不通过，原因："+reason;
                message.setType("3");
                message.setTopicId("5");
                message.setContent(content);
                message.setUserId(userId);
                message=messageService.save(message);

                MessageSend messageSend=new MessageSend();
                messageSend.setUserId(userId);
                messageSend.setMessageId(message.getId());
                messageSend.setType("3");
                messageSendService.save(messageSend);
                msgContent=content;
            }else {
                Message message = new Message();
                message.setTitle("实名认证");
                String content="您的提交的“实名认证”已经通过审核啦！";
                logContent="实名认证信息审核通过";
                message.setType("3");
                message.setTopicId("5");
                message.setContent(content);
                message.setUserId(userId);
                message=messageService.save(message);

                MessageSend messageSend=new MessageSend();
                messageSend.setUserId(userId);
                messageSend.setMessageId(message.getId());
                messageSend.setType("3");
                messageSendService.save(messageSend);
                msgContent=content;

            }
            driverUserService.save(driverUser);

            //极光推送
            MyJPushClient jPushUtil = new MyJPushClient();
            List<String> aliasList = Arrays.asList(u.getUsername());
            jPushUtil.sendToAliasList( aliasList,notificationTitle, msgTitle, msgContent, "1",null,registState,null,null);

            //操作记录
            operationLogService.saveOperationLog(2,logContent,userId.toString());
        } else {
            //货主
            CompanyUser companyUser=companyUserService.findByUserId(userId);
            companyUser.setCompanyStatus(registState);
            companyUserService.save(companyUser);
            String content;
            if(registState == 0){
                //审核未通过，发送消息通知原因
                Message message = new Message();
                message.setTitle("实名认证");
                content="您的提交的“实名认证”审核未通过，原因："+reason+"。";
                logContent="货主信息审核不通过，原因："+reason;
                message.setType("3");
                message.setTopicId("5");
                message.setContent(content);
                message.setUserId(userId);
                message=messageService.save(message);

                MessageSend messageSend=new MessageSend();
                messageSend.setUserId(userId);
                messageSend.setMessageId(message.getId());
                messageSend.setType("3");
                messageSendService.save(messageSend);
            }else {
                Message message = new Message();
                message.setTitle("实名认证");
                content="您的提交的“实名认证”已经通过审核啦！";
                logContent="货主信息审核通过";
                message.setType("3");
                message.setTopicId("5");
                message.setContent(content);
                message.setUserId(userId);
                message=messageService.save(message);

                MessageSend messageSend=new MessageSend();
                messageSend.setUserId(userId);
                messageSend.setMessageId(message.getId());
                messageSend.setType("3");
                messageSendService.save(messageSend);
            }

            //操作记录
            operationLogService.saveOperationLog(1,logContent,userId.toString());
        }
        return "修改成功";
    }

    @Override
    public UserAdminVo getAdminInfo() {
        UserAdminVo userAdminVo = new UserAdminVo();
        User u = userService.get(1L);
        ObjectUtil.copyPropertiesIgnoreNull(u, userAdminVo);
        return userAdminVo;
    }

    @Override
    public void cancellationUser(Long userId) {
        User user = userService.get(userId);

        if(user.getUserType() == 1){
            DriverUser driverUser = driverVoMapper.getDriverVoUserId(userId);
            if(driverUser!=null){
                if(driverUser.getDriverUserStatus() == 0 || driverUser.getDriverUserStatus() == 2){
                    Integer driverNum = driverVoMapper.getOederdriverUser(userId);
                    if(driverNum > 0){
                        throw new FreightException("司机已有运单,不能注销");
                    }
                    if(driverUser.getIdCardId()!=null){
                        idCardDao.deleteById(driverUser.getIdCardId());
                    }



                    driverUserService.delete(driverUser.getId());
                }else {
                    throw new FreightException("账户已认证通过,不能注销");
                }
            }
            redisTemplate.delete("FREIGHT_USER_TOKEN::"+user.getUsername());
            redisTemplate.delete("user::"+user.getUsername());
            userService.delete(userId);

        }


    }


}